package me.android.library.utils.android;

import android.Manifest;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.telephony.TelephonyManager;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresPermission;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;

import cn.hutool.core.util.StrUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;


@Slf4j
@UtilityClass
public class NetworkUtil {
    final Set<Network> trackedNetworks = Sets.newHashSet();
    final ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
        // 当网络可用时回调
        @Override
        public void onAvailable(@NonNull Network network) {
            // 添加到跟踪列表
            trackedNetworks.add(network);
        }

        // 当网络丢失时回调
        @Override
        public void onLost(@NonNull Network network) {
            // 从跟踪列表移除
            trackedNetworks.remove(network);
        }
    };

    public void init() {
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();
        // 创建网络请求（可自定义过滤条件）
        NetworkRequest networkRequest = new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                .addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH)
                .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
                .build();

        cm.registerNetworkCallback(networkRequest, networkCallback);
    }

    public void dispose() {
        SystemServiceUtil.getConnectivityManager().unregisterNetworkCallback(networkCallback);
    }

    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
    public int getDataNetworkType() {
        return SystemServiceUtil.getTelephonyManager().getDataNetworkType();
    }

    public Collection<Network> getAllNetwork() {
        return trackedNetworks;
    }

    /**
     * 检查是否有网络连接（注意：可能连接但无 Internet 访问）
     */
    public boolean isNetworkConnected() {
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();
        Network network = cm.getActiveNetwork();
        if (network == null) return false;

        NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
        return capabilities != null && (
                capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) ||
                        capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
        );
    }

    /**
     * 判断是否有可用的网络连接（替代 NetworkInfo.isAvailable()）
     * 注意：此方法仅判断网络是否"连接"，不保证能访问互联网
     */
    @SuppressWarnings("all")
    public boolean isNetworkAvailable() {
        // 获取 ConnectivityManager 实例
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();

        // 适配 Android 10+（API 29+）
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // 获取当前活动网络
            Network network = cm.getActiveNetwork();
            if (network == null) {
                return false; // 无活动网络
            }

            // 获取网络能力
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
            if (capabilities == null) {
                return false; // 网络无可用能力
            }

            // 检查网络是否具备基本连接能力（如 WiFi/移动网络已连接）
            return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
        } else {
            // 适配 Android 10 以下（API 28 及更低）
            // 注意：getActiveNetworkInfo() 在 API 29 中已过时，仅作为兼容处理
            android.net.NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            // 替代 networkInfo.isAvailable() 和 networkInfo.isConnected()
            return networkInfo != null && networkInfo.isConnected();
        }
    }

    /**
     * 判断是否有可用的 WiFi 网络
     */
    @SuppressWarnings("all")
    public boolean isWifiAvailable() {
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            Network network = cm.getActiveNetwork();
            if (network == null) {
                return false;
            }

            NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
            return capabilities != null
                    && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) // 是 WiFi 网络
                    && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); // 具备互联网能力
        } else {
            // 旧版本兼容（API 28 及以下）
            android.net.NetworkInfo wifiInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            return wifiInfo != null && wifiInfo.isConnected();
        }
    }

    /**
     * 判断是否有可用的移动网络（4G/5G）
     */
    @SuppressWarnings("all")
    public boolean isMobileNetworkAvailable() {
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            Network network = cm.getActiveNetwork();
            if (network == null) {
                return false;
            }

            NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
            return capabilities != null
                    && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) // 是移动网络
                    && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); // 具备互联网能力
        } else {
            // 旧版本兼容
            android.net.NetworkInfo mobileInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            return mobileInfo != null && mobileInfo.isConnected();
        }
    }

    /**
     * 获取设备的本地 IPv4 地址（排除环回地址）
     *
     * @return IPv4 地址字符串，如获取失败则返回 null
     */
    public String getLocalIPv4Address() {
        try {
            // 枚举所有网络接口
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface ni = interfaces.nextElement();

                // 排除回环接口和未连接的接口
                if (ni.isLoopback() || !ni.isUp()) {
                    continue;
                }

                // 枚举该接口的所有 IP 地址
                Enumeration<InetAddress> addresses = ni.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress address = addresses.nextElement();

                    // 排除 IPv6 和环回地址，仅保留 IPv4
                    if (!address.isLoopbackAddress() && isIPv4Address(address.getHostAddress())) {
                        return address.getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            log.warn("获取本地ip异常", e);
        }
        return null;
    }

    /**
     * 判断是否为 IPv4 地址
     */
    private boolean isIPv4Address(String address) {
        if (address == null || address.isEmpty()) {
            return false;
        }
        // 简单验证格式（可替换为更严格的正则表达式）
        return address.indexOf(':') < 0; // IPv4 不包含冒号，IPv6 使用冒号分隔
    }

    /**
     * 获取默认mac地址
     */
    public String getLocalMac() {
        String ip = getLocalIPv4Address();
        return getMacByIp(ip);
    }

    /**
     * 获取默认ip对应的mac地址
     */
    public String getMacByIp(String ip) {
        if (Strings.isNullOrEmpty(ip)) return null;

        try {
            NetworkInterface ne = NetworkInterface.getByInetAddress(InetAddress.getByName(ip));
            byte[] bytes = ne.getHardwareAddress();
            return byte2hex(bytes);
        } catch (Exception e) {
            log.warn("获取MAC地址异常", e);
        }

        return null;
    }

    /**
     * 获取默认子网广播地址
     */
    public String getBroadcastAddress() {
        String broadcastAddr = "255.255.255.255";
        try {
            String localIp = getLocalIPv4Address();
            Preconditions.checkNotNull(localIp, "获取本地IP地址失败");
            NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName(localIp));

            if (!ni.isLoopback() && ni.isUp()) {
                List<InterfaceAddress> addressList = ni.getInterfaceAddresses();

                for (InterfaceAddress ia : addressList) {
                    if (ia.getBroadcast() != null) {
                        broadcastAddr = ia.getBroadcast().getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            log.warn("获取默认子网广播地址异常", e);
        }

        return broadcastAddr;
    }

    /**
     * 获取当前连接的 WiFi 网关 IP 地址（兼容 Android 10+）
     *
     * @return 网关 IP 地址（字符串形式），如获取失败则返回 null
     */
    public String getWifiGatewayIp() {
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();

        // 获取当前活动的网络
        Network activeNetwork = cm.getActiveNetwork();
        if (activeNetwork == null) {
            return null;
        }

        // 检查是否为 WiFi 网络
        NetworkCapabilities capabilities = cm.getNetworkCapabilities(activeNetwork);
        if (capabilities == null ||
                !capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            return null;
        }

        // 获取网络链接属性
        LinkProperties linkProperties = cm.getLinkProperties(activeNetwork);
        if (linkProperties == null) {
            return null;
        }

        // 遍历所有路由，查找默认网关
        for (android.net.RouteInfo route : linkProperties.getRoutes()) {
            if (route.isDefaultRoute()) {
                InetAddress gateway = route.getGateway();
                if (gateway instanceof Inet4Address) { // 仅返回 IPv4 网关
                    return gateway.getHostAddress();
                }
            }
        }

        // 如果未找到默认路由，尝试从 DHCP 信息获取（兼容 Android 10 以下）
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            return getLegacyWifiGatewayIp();
        }

        return null;
    }

    /**
     * 使用旧 API 获取 WiFi 网关 IP（Android 10 以下兼容方案）
     */
    private String getLegacyWifiGatewayIp() {
        WifiManager wifiManager = SystemServiceUtil.getWifiManager();
        if (wifiManager == null) {
            return null;
        }

        android.net.DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
        if (dhcpInfo == null) {
            return null;
        }

        // 将 int 类型的 IP 地址转换为字符串格式
        return formatIpAddress(dhcpInfo.gateway);
    }

    /**
     * 将 int 类型的 IP 地址转换为标准的点分十进制字符串格式
     */
    private String formatIpAddress(int ipAddress) {
        return (ipAddress & 0xFF) + "." +
                ((ipAddress >> 8) & 0xFF) + "." +
                ((ipAddress >> 16) & 0xFF) + "." +
                ((ipAddress >> 24) & 0xFF);
    }

    /**
     * 获取设备的活跃网络接口（已连接且非环回）
     *
     * @return 活跃网络接口列表
     */
    public List<NetworkInterface> getActiveNetworkInterfaces() {
        List<NetworkInterface> activeInterfaces = Lists.newArrayList();
        List<NetworkInterface> allInterfaces = getAllNetworkInterfaces();

        for (NetworkInterface ni : allInterfaces) {
            try {
                if (ni.isUp() && !ni.isLoopback()) {
                    activeInterfaces.add(ni);
                }
            } catch (Exception e) {
                log.warn("获取活跃网络接口异常", e);
            }
        }

        return activeInterfaces;
    }

    /**
     * 获取设备的所有网络接口（兼容 Android 5.0+）
     *
     * @return 网络接口列表
     */
    public List<NetworkInterface> getAllNetworkInterfaces() {
        List<NetworkInterface> interfaces = Lists.newArrayList();

        try {
            // Android 5.0+ (API 21+) 使用 ConnectivityManager 获取活跃网络
            ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();

            // 获取所有网络
            for (Network network : trackedNetworks) {
                // 获取网络的 LinkProperties
                LinkProperties linkProperties = cm.getLinkProperties(network);
                if (linkProperties != null) {
                    // 通过接口名称查找 NetworkInterface
                    String interfaceName = linkProperties.getInterfaceName();
                    if (interfaceName != null) {
                        NetworkInterface ni = findNetworkInterfaceByName(interfaceName);
                        if (ni != null && !interfaces.contains(ni)) {
                            interfaces.add(ni);
                        }
                    }
                }
            }

            // 传统方式获取所有网络接口（作为补充）
            Enumeration<NetworkInterface> enumInterfaces = NetworkInterface.getNetworkInterfaces();
            if (enumInterfaces != null) {
                while (enumInterfaces.hasMoreElements()) {
                    NetworkInterface ni = enumInterfaces.nextElement();
                    if (!interfaces.contains(ni)) {
                        interfaces.add(ni);
                    }
                }
            }
        } catch (Exception e) {
            log.warn("获取所有网络接口异常", e);
        }

        return interfaces;
    }

    /**
     * 判断当前网络连接是否为 WiFi（兼容所有 Android 版本）
     *
     * @return 如果是 WiFi 连接返回 true，否则返回 false
     */
    public boolean isConnectedToWiFi() {
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();

        // 适配 Android 10+ (API 29+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            Network network = cm.getActiveNetwork();
            if (network == null) {
                return false;
            }

            NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
            return capabilities != null &&
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
        }
        // 适配 Android 5.0-9.0 (API 21-28)
        else {
            Network[] networks = cm.getAllNetworks();
            for (Network network : networks) {
                NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
                if (capabilities != null &&
                        capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
                        capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 判断当前移动网络是否为快速网络（4G/5G）
     */
    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
    public boolean isFastMobileNetwork() {
        ConnectivityManager cm = SystemServiceUtil.getConnectivityManager();

        // 1. 先判断是否为移动网络（排除 WiFi/以太网等）
        if (!isMobileNetwork(cm)) {
            return false;
        }

        // 2. 获取移动网络类型，判断是否为 4G/5G
        int networkType = getMobileNetworkType();
        return isFastNetworkType(networkType);
    }

    /**
     * 判断当前是否为移动网络（蜂窝网络）
     */
    private boolean isMobileNetwork(ConnectivityManager cm) {
        Network activeNetwork = cm.getActiveNetwork();
        if (activeNetwork == null) return false;
        NetworkCapabilities capabilities = cm.getNetworkCapabilities(activeNetwork);
        return capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
    }

    /**
     * 获取当前移动网络类型（仅在 API 29 以下使用）
     */
    @SuppressWarnings("all")
    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
    private int getMobileNetworkType() {
        TelephonyManager tm = SystemServiceUtil.getTelephonyManager();

        // API 30+ 推荐使用 getNetworkClass()，但为兼容旧版本仍使用 getNetworkType()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            return tm.getDataNetworkType();
        } else {
            return tm.getNetworkType();
        }
    }

    /**
     * 判断移动网络类型是否为快速网络
     */
    private boolean isFastNetworkType(int networkType) {
        return switch (networkType) {
            // 2G/3G 网络（慢速）
            case TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE,
                 TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_1xRTT,
                 TelephonyManager.NETWORK_TYPE_IDEN, TelephonyManager.NETWORK_TYPE_UMTS,
                 TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyManager.NETWORK_TYPE_EVDO_A,
                 TelephonyManager.NETWORK_TYPE_HSDPA, TelephonyManager.NETWORK_TYPE_HSUPA,
                 TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_EVDO_B,
                 TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyManager.NETWORK_TYPE_HSPAP -> false;

            // 4G/5G 网络（快速）
            // TelephonyManager.NETWORK_TYPE_LTE_CA (API 21+)
            case TelephonyManager.NETWORK_TYPE_LTE, 19,
                 20 -> // TelephonyManager.NETWORK_TYPE_NR (5G, API 29+)
                    true;

            // 未知类型
            default -> false;
        };
    }

    /**
     * 根据接口名称查找 NetworkInterface
     */
    private NetworkInterface findNetworkInterfaceByName(String interfaceName) {
        try {
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface ni = interfaces.nextElement();
                if (ni.getName().equals(interfaceName)) {
                    return ni;
                }
            }
        } catch (Exception e) {
            log.warn("获取网络接口异常", e);
        }
        return null;
    }

    private String byte2hex(byte[] b) {
        StringBuffer hs = new StringBuffer(b.length);
        String stmp = StrUtil.EMPTY;
        for (byte value : b) {
            stmp = Integer.toHexString(value & 0xFF);
            if (stmp.length() == 1) hs = hs.append("0").append(stmp);
            else {
                hs = hs.append(stmp);
            }
        }
        return String.valueOf(hs);
    }
}
